﻿namespace Unity.AzureSetting.Injector
{
    using System;
    using System.ComponentModel;
    using System.Configuration;
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.Configuration;
    using Microsoft.WindowsAzure.ServiceRuntime;

    public class ConfigurationSettingParameterValueElement : ParameterValueElement
    {
        /// <summary>
        /// Defines the attribute name for the <see cref="ConfigurationSettingKey"/> property.
        /// </summary>
        public const string ConfigurationSettingKeyAttributeName = "key";

        /// <summary>
        /// Defines the configuration element name used to identify this type of parameter value element.
        /// </summary>
        public const String ElementName = "azureSetting";

        /// <summary>
        /// Defines the attribute name for the <see cref="TypeConverterTypeName"/> property.
        /// </summary>
        public const string ConfigurationSettingTypeAttributeName = "type";

        /// <summary>
        /// Initializes a new instance of the <see cref="ConfigurationSettingParameterValueElement"/> class.
        /// </summary>
        public ConfigurationSettingParameterValueElement()
        {

        }

        /// <summary>
        /// Creates the value.
        /// </summary>
        /// <param name="parameterType">
        /// Type of the parameter.
        /// </param>
        /// <returns>
        /// A <see cref="Object"/> instance.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="parameterType"/> value is <c>null</c>.
        /// </exception>
        public Object CreateValue(Type parameterType)
        {
            if (parameterType == null)
            {
                throw new ArgumentNullException("parameterType");
            }

            
            Object injectionValue;

            switch(this.ConfigurationSettingType)
            {
                case AzureConfigurationType.LocalStorage:
                    injectionValue = RoleEnvironment.GetLocalResource(this.ConfigurationSettingKey).RootPath;
                    break;
                case AzureConfigurationType.ConfigSetting:
                case AzureConfigurationType.ConnectionString:
                default:
                    injectionValue = RoleEnvironment.GetConfigurationSettingValue(this.ConfigurationSettingKey);
                    break;
            }


            return injectionValue;
        }

        /// <summary>
        /// Generate an <see cref="T:Microsoft.Practices.Unity.InjectionParameterValue"/> object
        ///   that will be used to configure the container for a type registration.
        /// </summary>
        /// <param name="container">
        /// Container that is being configured. Supplied in order
        ///   to let custom implementations retrieve services; do not configure the container
        ///   directly in this method.
        /// </param>
        /// <param name="parameterType">
        /// Type of the.
        /// </param>
        /// <returns>
        /// An <see cref="InjectionParameterValue"/> instance.
        /// </returns>
        public override InjectionParameterValue GetInjectionParameterValue(IUnityContainer container, Type parameterType)
        {
            Object injectionValue = CreateValue(parameterType);

            return new InjectionParameter(parameterType, injectionValue);
        }

        /// <summary>
        /// Gets or sets the Azure configuration setting key.
        /// </summary>
        /// <value>
        /// The Azure configuration setting key.
        /// </value>
        [ConfigurationProperty(ConfigurationSettingKeyAttributeName, IsRequired = true)]
        public String ConfigurationSettingKey
        {
            get
            {
                return (String)base[ConfigurationSettingKeyAttributeName];
            }

            set
            {
                base[ConfigurationSettingKeyAttributeName] = value;
            }
        }

        /// <summary>
        /// Gets or sets the name of the type of Azure Setting to read. Available options are:
        /// config,storage,endpoint
        /// </summary>
        /// <value>
        /// The name of the type converter type.
        /// </value>
        [ConfigurationProperty(ConfigurationSettingTypeAttributeName, IsRequired = false, DefaultValue = null)]
        public AzureConfigurationType ConfigurationSettingType
        {
            get
            {
                return (AzureConfigurationType)base[ConfigurationSettingTypeAttributeName];
            }

            set
            {
                base[ConfigurationSettingTypeAttributeName] = value;
            }
        }

    }
}